//
// Created by LONG on 2020/10/18.
//

#ifndef CSP_INCLUDE_UTILS_FSM_H_
#define CSP_INCLUDE_UTILS_FSM_H_


#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "commDef.h"

#ifdef __cplusplus
extern "C"
{
#endif

#define FSM_STATE_NUM_MAX 64
#define FSM_EVENT_NUM_MAX 64
#define FSM_TRANS_NUM_MAX 64

enum
{
    FSM_RC_OK,
    FSM_RC_ERR,
    FSM_RC_STATE_ERR,
    FSM_RC_EVENT_ERR,
    FSM_RC_TRANS_ERR,
    FSM_RC_MAX,
};

enum
{
    FSM_LOG_TYPE_ERR,
    FSM_LOG_TYPE_STATE_TRANS
};

typedef struct FsmEventContext
{
    void    *context;
    uint32_t event;
} S_FsmEventContext;

typedef struct FsmHandleResult
{
    uint32_t procRslt;
    uint32_t newEventInd;
    void    *newContext;
    uint32_t newEvent;
} S_FsmHandleResult;

/* 日志输出回调函数 */
typedef void (*FsmLogCallback)(uint32_t logType, const char *fmt, ...);
/* 事件处理回调函数 */
typedef void (*FsmEventHandleFunc)(uint32_t state, S_FsmEventContext *evtCtxt, S_FsmHandleResult *result);

typedef struct Fsm S_Fsm;
typedef struct FsmState S_FsmState;
typedef struct FsmEventHandle S_FsmEventHandle;
typedef struct FsmStateTrans S_FsmStateTrans;
typedef struct FsmInst S_FsmInst;

#define FSM_DEF_BEG(FSM_ID, INIT_STATE) \
S_Fsm* FSM_##FSM_ID##_init()\
{\
    S_Fsm *fsm;\
    uint32_t state;\
    S_FsmState *smState;\
    S_FsmEventHandle *smEventHandle;\
    S_FsmStateTrans *smStateTrans;\
    fsm = FSM_IFUNC_InitFsm(#FSM_ID, INIT_STATE);\
    if (NULL == fsm) { return NULL; }

#define FSM_STATE_DEF_BEG(STATE) \
    state = STATE;\
    smState = FSM_IFUNC_InitState(fsm, STATE, #STATE);\
    if (NULL == smState) { return NULL; }

#define FSM_DEFAULT_EVENT_HANDLE_DEF(HANDLE) \
    smEventHandle = FSM_IFUNC_InitDefaultEventHandle(smState, HANDLE);\
    if (NULL == smEventHandle) { return NULL; }

#define FSM_EVENT_HANDLE_DEF(EVENT, HANDLE) \
    smEventHandle = FSM_IFUNC_InitEventHandle(smState, EVENT, #EVENT, HANDLE);\
    if (NULL == smEventHandle) { return NULL; }

#define FSM_STATE_TRANS_DEF(PROC_RESULT, NEXT_STATE) \
    smStateTrans = FSM_IFUNC_InitStateTrans(smEventHandle, PROC_RESULT, NEXT_STATE, #NEXT_STATE);\
    if (NULL == smStateTrans) { return NULL; }

#define FSM_STATE_DEF_END(STATE) \
    if (state != STATE) { return NULL; }

#define FSM_DEF_END(FSM_ID) \
    return fsm;\
}

#define FSM_INIT(FSM_ID) FSM_##FSM_ID##_init()
void FSM_Final(S_Fsm *sm);
void FSM_SetLogCallback(S_Fsm *sm, FsmLogCallback callback);

S_FsmInst* FSM_INST_Init(S_Fsm *sm, const char* instIdStr);
void FSM_INST_Final(S_FsmInst *smInst);
void FSM_INST_Reset(S_FsmInst *smInst);
uint32_t FSM_INST_GetState(S_FsmInst *smInst);
void FSM_INST_SetState(S_FsmInst *smInst, uint32_t state);
int32_t FSM_INST_HandleEvent(S_FsmInst *smInst, S_FsmEventContext *evtCtxt);

/* 以下为内部使用函数 */
S_Fsm* FSM_IFUNC_InitFsm(const char* fsmId, uint32_t initState);
S_FsmState* FSM_IFUNC_InitState(S_Fsm *sm, uint32_t state, const char* stateStr);
S_FsmEventHandle* FSM_IFUNC_InitEventHandle(S_FsmState *smState, uint32_t event, const char* eventStr, FsmEventHandleFunc handleFunc);
S_FsmEventHandle* FSM_IFUNC_InitDefaultEventHandle(S_FsmState *smState, FsmEventHandleFunc handleFunc);
S_FsmStateTrans* FSM_IFUNC_InitStateTrans(S_FsmEventHandle *smEventHandle, uint32_t procRslt, uint32_t nextState, const char* nextStateStr);

#ifdef __cplusplus
}
#endif

#endif //CSP_INCLUDE_UTILS_FSM_H_
